//=============================================================================
#include "CLua.h"
#include "CLuaAPI.h"

//=============================================================================
CLua CLua::LuaControl;

//=============================================================================
CLua::CLua() {
    Lua_Handle = NULL;

	NumArgs = 0;
}

//==============================================================================
bool CLua::OnInit() {
    Lua_Handle = lua_open();

    luaL_openlibs(Lua_Handle);

    lua_register(Lua_Handle, "Camera_SetCenter", Lua_Camera_SetCenter);
    lua_register(Lua_Handle, "Camera_SetCenterToEntity", Lua_Camera_SetCenterToEntity);
    lua_register(Lua_Handle, "Camera_SetCenterToPlayer", Lua_Camera_SetCenterToPlayer);
    lua_register(Lua_Handle, "Camera_SetPosition", Lua_Camera_SetPosition);
    lua_register(Lua_Handle, "Camera_Move", Lua_Camera_Move);

    lua_register(Lua_Handle, "Chat_Clear", Lua_Chat_Clear);
    lua_register(Lua_Handle, "Chat_Say", Lua_Chat_Say);

    lua_register(Lua_Handle, "Entity_Add", Lua_Entity_Add);
    lua_register(Lua_Handle, "Entity_CreateSpawnPoint", Lua_Entity_CreateSpawnPoint);
    lua_register(Lua_Handle, "Entity_FollowEntity", Lua_Entity_FollowEntity);
    lua_register(Lua_Handle, "Entity_FollowPlayer", Lua_Entity_FollowPlayer);
    lua_register(Lua_Handle, "Entity_GetHealth", Lua_Entity_GetHealth);
    lua_register(Lua_Handle, "Entity_Heal", Lua_Entity_Heal);
    lua_register(Lua_Handle, "Entity_Hurt", Lua_Entity_Hurt);
    lua_register(Lua_Handle, "Entity_Move", Lua_Entity_Move);
    lua_register(Lua_Handle, "Entity_Remove", Lua_Entity_Remove);
    lua_register(Lua_Handle, "Entity_RemoveSpawnPoint", Lua_Entity_RemoveSpawnPoint);
    lua_register(Lua_Handle, "Entity_Say", Lua_Entity_Say);
    lua_register(Lua_Handle, "Entity_SetAlpha", Lua_Entity_SetAlpha);
    lua_register(Lua_Handle, "Entity_SetAnimation", Lua_Entity_SetAnimation);
    lua_register(Lua_Handle, "Entity_SetAnimationLoop", Lua_Entity_SetAnimationLoop);
    lua_register(Lua_Handle, "Entity_SetAnimationSpeed", Lua_Entity_SetAnimationSpeed);
    lua_register(Lua_Handle, "Entity_SetDimensions", Lua_Entity_SetDimensions);
    lua_register(Lua_Handle, "Entity_SetHealth", Lua_Entity_SetHealth);
    lua_register(Lua_Handle, "Entity_SetPosition", Lua_Entity_SetPosition);
    lua_register(Lua_Handle, "Entity_SetRotation", Lua_Entity_SetRotation);

    lua_register(Lua_Handle, "FontEngine_Load", Lua_FontEngine_Load);
    lua_register(Lua_Handle, "FontEngine_Print", Lua_FontEngine_Print);
    lua_register(Lua_Handle, "FontEngine_PrintDialog", Lua_FontEngine_PrintDialog);

    lua_register(Lua_Handle, "Image_Add", Lua_Image_Add);
    lua_register(Lua_Handle, "Image_Move", Lua_Image_Move);
    lua_register(Lua_Handle, "Image_Remove", Lua_Image_Remove);
    lua_register(Lua_Handle, "Image_SetAlpha", Lua_Image_SetAlpha);
    lua_register(Lua_Handle, "Image_SetAnimation", Lua_Image_SetAnimation);
    lua_register(Lua_Handle, "Image_SetAnimationLoop", Lua_Image_SetAnimationLoop);
    lua_register(Lua_Handle, "Image_SetAnimationSpeed", Lua_Image_SetAnimationSpeed);
    lua_register(Lua_Handle, "Image_SetDimensions", Lua_Image_SetDimensions);
    lua_register(Lua_Handle, "Image_SetPosition", Lua_Image_SetPosition);
    lua_register(Lua_Handle, "Image_SetRotation", Lua_Image_SetRotation);

    lua_register(Lua_Handle, "Light_Add", Lua_Light_Add);
    lua_register(Lua_Handle, "Light_Global", Lua_Light_Global);
    lua_register(Lua_Handle, "Light_Remove", Lua_Light_Remove);
    lua_register(Lua_Handle, "Light_SetAlpha", Lua_Light_SetAlpha);
    lua_register(Lua_Handle, "Light_SetColor", Lua_Light_SetColor);

    lua_register(Lua_Handle, "Music_Add", Lua_Music_Add);
    lua_register(Lua_Handle, "Music_Loop", Lua_Music_Loop);
    lua_register(Lua_Handle, "Music_Play", Lua_Music_Play);
    lua_register(Lua_Handle, "Music_Queue", Lua_Music_Queue);
    lua_register(Lua_Handle, "Music_SetVolume", Lua_Music_SetVolume);

    lua_register(Lua_Handle, "Player_Ban", Lua_Player_Ban);
    lua_register(Lua_Handle, "Player_DisableProperty", Lua_Player_DisableProperty);
    lua_register(Lua_Handle, "Player_Disconnect", Lua_Player_Disconnect);
    lua_register(Lua_Handle, "Player_EnableProperty", Lua_Player_EnableProperty);
    lua_register(Lua_Handle, "Player_GetHealth", Lua_Player_GetHealth);
    lua_register(Lua_Handle, "Player_GetValue", Lua_Player_GetValue);
    lua_register(Lua_Handle, "Player_Heal", Lua_Player_Heal);
    lua_register(Lua_Handle, "Player_Hurt", Lua_Player_Hurt);
    lua_register(Lua_Handle, "Player_IsBanned", Lua_Player_IsBanned);
    lua_register(Lua_Handle, "Player_Move", Lua_Player_Move);
    lua_register(Lua_Handle, "Player_Say", Lua_Player_Say);
    lua_register(Lua_Handle, "Player_SetAlpha", Lua_Player_SetAlpha);
    lua_register(Lua_Handle, "Player_SetAnimation", Lua_Player_SetAnimation);
    lua_register(Lua_Handle, "Player_SetAnimationLoop", Lua_Player_SetAnimationLoop);
    lua_register(Lua_Handle, "Player_SetAnimationSpeed", Lua_Player_SetAnimationSpeed);
    lua_register(Lua_Handle, "Player_SetDimensions", Lua_Player_SetDimensions);
    lua_register(Lua_Handle, "Player_SetHealth", Lua_Player_SetHealth);
    lua_register(Lua_Handle, "Player_SetPosition", Lua_Player_SetPosition);
    lua_register(Lua_Handle, "Player_SetRotation", Lua_Player_SetRotation);
    lua_register(Lua_Handle, "Player_SetValue", Lua_Player_SetValue);
    lua_register(Lua_Handle, "Player_Warp", Lua_Player_Warp);

    lua_register(Lua_Handle, "SoundBank_Add", Lua_SoundBank_Add);
    lua_register(Lua_Handle, "SoundBank_Play", Lua_SoundBank_Play);
    lua_register(Lua_Handle, "SoundBank_Remove", Lua_SoundBank_Remove);
    lua_register(Lua_Handle, "SoundBank_SetPosition", Lua_SoundBank_SetPosition);
    lua_register(Lua_Handle, "SoundBank_SetVolume", Lua_SoundBank_SetVolume);

    lua_register(Lua_Handle, "System_GetFPS", Lua_System_GetFPS);
    lua_register(Lua_Handle, "System_GetSpeedFactor", Lua_System_GetSpeedFactor);
    lua_register(Lua_Handle, "System_GetUptime", Lua_System_GetUptime);
    lua_register(Lua_Handle, "System_GetValue", Lua_System_GetValue);
    lua_register(Lua_Handle, "System_LogError", Lua_System_LogError);
    lua_register(Lua_Handle, "System_LogNotice", Lua_System_LogNotice);
    lua_register(Lua_Handle, "System_SetValue", Lua_System_SetValue);

    lua_register(Lua_Handle, "Timer_GetElapsedTime", Lua_Timer_GetElapsedTime);
    lua_register(Lua_Handle, "Timer_Pause", Lua_Timer_Pause);
    lua_register(Lua_Handle, "Timer_Start", Lua_Timer_Start);
    lua_register(Lua_Handle, "Timer_Stop", Lua_Timer_Stop);

    // Primary Server Script Only
    lua_setConst(Lua_Handle, EVENT_PLAYER_LOGGED_IN);
    lua_setConst(Lua_Handle, EVENT_PLAYER_LOGGED_OUT);
    lua_setConst(Lua_Handle, EVENT_PLAYER_DISCONNECTED);

    // Primary Server Script + Area Scripts
    lua_setConst(Lua_Handle, EVENT_PLAYER_ENTERED_AREA);
    lua_setConst(Lua_Handle, EVENT_PLAYER_LEFT_AREA);
    lua_setConst(Lua_Handle, EVENT_PLAYER_ENTERED_MAP);
    lua_setConst(Lua_Handle, EVENT_PLAYER_LEFT_MAP);

    // All Scripts
    lua_setConst(Lua_Handle, EVENT_PLAYER_DIED);
    lua_setConst(Lua_Handle, EVENT_PLAYER_KILLED_PLAYER);
    lua_setConst(Lua_Handle, EVENT_PLAYER_KILLED_ENTITY);
    lua_setConst(Lua_Handle, EVENT_PLAYER_OPEN);
    lua_setConst(Lua_Handle, EVENT_PLAYER_PUSH);
    lua_setConst(Lua_Handle, EVENT_PLAYER_PULL);

    lua_setConst(Lua_Handle, PLAYER_PROPERTY_CONTROLS);
    lua_setConst(Lua_Handle, PLAYER_PROPERTY_COLLISION);
    lua_setConst(Lua_Handle, PLAYER_PROPERTY_INVINCIBLE);

    return true;
}

//-----------------------------------------------------------------------------
bool CLua::OnLoad(std::string Filename) {
    if(luaL_loadfile(Lua_Handle, Filename.c_str()) == 0) {
        if(lua_pcall(Lua_Handle, 0, 1, 0) != 0){
            std::string Error = lua_tostring(Lua_Handle, -1);

            CLog::Error("Bad Lua file : " + Error);
            return false;
        }
    }else{
        std::string Error = lua_tostring(Lua_Handle, -1);

        CLog::Error("Unable to load Lua file : " + Error);
        return false;
    }

    return true;
}

//-----------------------------------------------------------------------------
void CLua::OnCleanup() {
    lua_close(Lua_Handle);
}

//=============================================================================
bool CLua::PushFunction(char* Function) {
    if(Lua_Handle == NULL) return false;

	lua_getglobal(Lua_Handle, Function);

	//How expensive am I?
	if(lua_isfunction(Lua_Handle, lua_gettop(Lua_Handle)) == false) {
		return false;
	}

	NumArgs = 0;

	return true;
}

//-----------------------------------------------------------------------------
void CLua::PushArgNumber(float Value) {
    if(Lua_Handle == NULL) return;

	lua_pushnumber(Lua_Handle, Value);

	NumArgs++;
}

//-----------------------------------------------------------------------------
void CLua::PushArgString(std::string String) {
    if(Lua_Handle == NULL) return;

	lua_pushstring(Lua_Handle, String.c_str());

	NumArgs++;
}

//=============================================================================
int CLua::Call() {
    if(Lua_Handle == NULL) return 0;

    if(lua_pcall(Lua_Handle, NumArgs, 1, 0) != 0) {
        std::string Error = lua_tostring(Lua_Handle, -1);

        CLog::Error("Syntax Error : " + Error);
		return 0;
    }

	int Return = (int)lua_tointeger(Lua_Handle, -1);

	lua_pop(Lua_Handle, 1);

	return Return;
}

//=============================================================================
